package com.htfyun.ft.agingtest;

import android.os.Bundle;
import android.os.Message;
import android.view.KeyEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

import com.htfyun.ft.BaseActivity;
import com.htfyun.ft.R;
import com.htfyun.ft.common.FTUtils;
import com.htfyun.ft.utils.DebugLog;
import com.htfyun.hardware.HallStateController;
import com.htfyun.hardware.KeyEventController;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import androidx.annotation.Nullable;

public class AgingTestActivity extends BaseActivity {

    private ViewGroup container;

    AgingTestItemBase currentItem;

    private List<AgingTestItemBase> agingTestItemList = new ArrayList<>();


    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_aging_test);

        View btnFinish = findViewById(R.id.btnFinish);
        if (btnFinish != null) {
            btnFinish.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    exitAging(false);
                }
            });
        }

        container = (ViewGroup) findViewById(R.id.container);

        for (AgingTestItemAttr attr : AgingTestItemAttr.values()) {
            AgingTestItemBase item = attr.getAgingTestItem();
            if (item != null) {
                item.setContext(this);
                item.setRootView(container);
                agingTestItemList.add(item);
            }
        }

        Collections.sort(agingTestItemList);

        updateTxtTips();

        setStateEnabledAndInitStartTimeAbsolute();

        getHandler().sendEmptyMessage(MSG_TIME_TICK);

    }

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {

        KeyEventController.RK_KEY key = KeyEventController.getInstance().getRKKeyByKeyCode(keyCode);

        if (key != null) {

            String status = getString(R.string.test_key_current_keycode_status_down);
            String name = key.getKeyLabel();

            updateTxtKeyInfo(getString(R.string.test_key_current_keycode, keyCode, status, name));

        }

        return super.onKeyDown(keyCode, event);
    }

    @Override
    public boolean onKeyUp(int keyCode, KeyEvent event) {

        KeyEventController.RK_KEY key = KeyEventController.getInstance().getRKKeyByKeyCode(keyCode);

        if (key != null) {

            String status = getString(R.string.test_key_current_keycode_status_up);
            String name =  key.getKeyLabel();
            updateTxtKeyInfo(getString(R.string.test_key_current_keycode, keyCode, status, name));

        }

        return super.onKeyUp(keyCode, event);
    }

    @Override
    protected void onResume() {
        super.onResume();
        HallStateController.getInstance().registerHallStateChangedListener(onHallStateChangedListener);
    }

    @Override
    protected void onPause() {
        super.onPause();
        HallStateController.getInstance().unregisterHallStateChangedListener(onHallStateChangedListener);
        exitAging(false);
    }


    private HallStateController.OnHallStateChangedListener onHallStateChangedListener =
            new HallStateController.OnHallStateChangedListener() {
                @Override
                public void onHallStateChangedListener(boolean isHallOn) {
                    updateTxtHallInfo(getString(R.string.test_hall_state, isHallOn ? 1 : 0));
                }
            };

    @Override
    protected void onDestroy() {
        super.onDestroy();

        DebugLog.e("onDestroy");

        doDestroy();

    }

    private volatile boolean isDestroy = false;
    private synchronized void doDestroy() {

        if (isDestroy) {
            return;
        }

        isDestroy = true;

        DebugLog.e("doDestroy");

        getHandler().removeMessages(MSG_TIME_TICK);

        for (AgingTestItemBase item : agingTestItemList) {
            item.stopTest();
        }
        currentItem = null;
        agingTestItemList.clear();
    }

    private String buildAgingTestTips() {

        StringBuilder sb = new StringBuilder();
        for (AgingTestItemBase itemBase : agingTestItemList) {
            if (itemBase.getAgingTestItemAttr() == null) {
                continue;
            }
            if (itemBase.getAgingTestItemAttr().isForceTestOver()) {
                continue;
            }
            sb.append(itemBase.getAgingTestItemAttr().getId());
            sb.append(". ");
            sb.append(itemBase.getAgingTestItemAttr().getDetail());
        }

        return getString(R.string.aging_test_tips, sb.toString());

    }

    private void updateTxtTips() {
        TextView txt = (TextView) findViewById(R.id.txtTips);

        if (txt != null) {
            if (AgingBooleanSettingsAttr.no_show_tips.get()) {
                txt.setVisibility(View.GONE);
            } else {
                txt.setVisibility(View.VISIBLE);
            }
            txt.setText(buildAgingTestTips());
        }
    }

    private void updateTxtHallInfo(String hallInfo) {
        TextView txt = (TextView) findViewById(R.id.txtHallInfo);
        if (txt != null) {
            txt.setText(hallInfo);
        }
    }

    private void updateTxtKeyInfo(String keyInfo) {
        TextView txt = (TextView) findViewById(R.id.txtKeyInfo);
        if (txt != null) {
            txt.setText(keyInfo);
        }
    }

    private void updateItemTxtInfo() {
        TextView txt = (TextView) findViewById(R.id.txtInfo);
        if (txt != null && currentItem != null) {
            txt.setText(currentItem.getInfoString());
        }
    }

    private void updateCurrentTestItemInfo(String info) {
        TextView txt = (TextView) findViewById(R.id.txtCurrentItem);
        if (txt != null) {
            txt.setText(info);

        }
    }

    private void periodicCheckItemTest() {

        updateItemTxtInfo();
        startAgingItemTest();
    }

    private void startAgingItemTest() {

        AgingTestItemBase item = null;

        for (AgingTestItemBase testItem : agingTestItemList) {
            if (testItem.getAgingTestItemAttr() == null) {
                continue;
            }

            if (testItem.getAgingTestItemAttr().isTestOver()) {

                if (testItem.isTestStarted()) {
                    testItem.stopTest();
                }

            } else if (item == null) {

                item = testItem;
                currentItem = testItem;
            }
        }

        if (item == null) {
            //测试完了.
            exitAging(true);

        } else if (!item.isTestStarted()) {

            item.startTest();
            updateCurrentTestItemInfo(getString(R.string.aging_test_item_current, item.getAgingTestItemAttr().getNominalName()));
        }
    }

    private void setStateEnabledAndInitStartTimeAbsolute() {

        boolean enabled = AgingBooleanSettingsAttr.aging_enabled.get();
        if (enabled) {
            return;
        }

        AgingBooleanSettingsAttr.aging_enabled.set(true);

        final long now = System.currentTimeMillis();

        if (!AgingBooleanSettingsAttr.aging_exit_ok.get() && AgingBooleanSettingsAttr.keep_record.get()) {

            DebugLog.e("init all startTime with (now - (exitTime - startTime))");

            long startTime = AgingLongSettingsAttr.aging_time_start_absolute.get();
            long exitTime = AgingLongSettingsAttr.aging_time_exit_absolute.get();

            AgingLongSettingsAttr.aging_time_start_absolute.set(now - (exitTime - startTime));
            AgingLongSettingsAttr.aging_time_exit_absolute.set(now);

            for (AgingTestItemAttr attr : AgingTestItemAttr.values()) {
                if (attr.isTestOver()) {
                    continue;
                }

                long startTimeOfItem = attr.getStartTimeAbsolute_ms();

                attr.setStartTimeAbsolute_ms(now - (exitTime - startTimeOfItem));
                attr.setExitTimeAbsolute_ms(now);

            }

        } else {

            DebugLog.e("init all startTime with now = " + now);

            AgingLongSettingsAttr.aging_time_start_absolute.set(now);

            for (AgingTestItemAttr attr : AgingTestItemAttr.values()) {
                attr.setStartTimeAbsolute_ms(now);
            }
        }

    }


    private volatile boolean isExitAging = false;
    private final Object lock = new Object();

    private void exitAging(boolean keepRecord) {
        getHandler().obtainMessage(MSG_EXIT_AGING, keepRecord ? 1 : 0, 0).sendToTarget();
    }

    private void doExitAging(boolean keepRecord) {

        synchronized (lock) {
            if (isExitAging) {
                return;
            }
            isExitAging = true;

        }

        AgingLongSettingsAttr.aging_time_exit_absolute.set(System.currentTimeMillis());

        boolean ok = true;
        if (keepRecord ) {

            AgingBooleanSettingsAttr.aging_exit_ok.set(true);

            for (AgingTestItemBase item : agingTestItemList) {
                if (item.getAgingTestItemAttr() == null) {
                    continue;
                }
                if (!item.getAgingTestItemAttr().isTestOver()) {
                    ok = false;
                    AgingBooleanSettingsAttr.aging_exit_ok.set(false);
                    break;
                }
            }

            if (AgingBooleanSettingsAttr.emmc_fail.get()) {
                ok = false;
            }
            if (AgingBooleanSettingsAttr.cpu_fail.get()) {
                ok = false;
            }
            if (AgingBooleanSettingsAttr.hardware_fail.get()) {
                ok = false;
            }

        } else {

            ok = false;

        }

        doDestroy();

        AgingBooleanSettingsAttr.keep_record.set(keepRecord);
        AgingBooleanSettingsAttr.aging_enabled.set(false);

        AgingBooleanSettingsAttr.aging_test_ok.set(ok);

        AgingTestItemAttr.saveLog();

        if (!keepRecord) {
            AgingTestItemAttr.clearAgingAll();
        }

        finish();
    }


    private final static int MSG_TIME_TICK = 99;
    private final static int PERIOD_TIME_TICK = 1000;

    private final static int MSG_EXIT_AGING = 100;

    @Override
    protected void handleMessage(Message msg) {
        switch (msg.what) {
            case MSG_EXIT_AGING:
                doExitAging(msg.arg1 != 0);
                break;
            case MSG_TIME_TICK:
                long tick = AgingLongSettingsAttr.aging_time_tick.get();
                tick += PERIOD_TIME_TICK;
                AgingLongSettingsAttr.aging_time_tick.set(tick);

                AgingLongSettingsAttr.aging_time_exit_absolute.set(System.currentTimeMillis());

                if (!isDestroy) {

                    if (!FTUtils.isInAgingTest()) {
                        //外部原因导致他已经退出老化测试了, 比如在老化测试时, 发送清除老化测试数据的广播.
                        //延迟退出是为了避免跟正常退出时冲突.
                        DebugLog.e("Aging test is disabled, exit!!!");
                        exitAging(false);

                    } else {

                        periodicCheckItemTest();

                        getHandler().sendEmptyMessageDelayed(msg.what, PERIOD_TIME_TICK);
                    }
                }

        }
    }

}
